﻿using NetEasyMusic.Lib.Models;
using NetEasyMusic.Lib.Operations;
using Newtonsoft.Json.Linq;

namespace NetEasyMusic.Lib.Data;

public class User : DataBasic
{
    public User(string cookie) : base(cookie)
    {
    }

    public User()
    {
    }

    public User(string url, bool isUse = false) : base(url, isUse)
    {
    }

    /// <summary>
    ///     如果是使用cookie字段的话，必须要先使用这个，保存登录状态才可以
    /// </summary>
    /// <returns></returns>
    public async Task<UserModel?> GetUserInfo()
    {
        var context = await GetFormString($"/user/account?cookie={Cookie}");
        if (context?["code"]?.ToObject<string>() != "200") return null;
        var token = context["account"];
        if (token is null or JValue) return null;

        var user = new UserModel { UserId = token["id"]?.ToObject<string>()! };

        token = context["profile"];
        if (token is null or JValue)
        {
            user.IsVisitor = true;
        }
        else
        {
            user.Nickname = token["nickname"]?.ToObject<string>()!;
            user.AvatarUrl = token["avatarUrl"]?.ToObject<string>()!;
            user.BackgroundUrl = token["backgroundUrl"]?.ToObject<string>()!;
        }

        context = await GetFormString($"/vip/info?uid={user.UserId}");
        user.VipUrl = context?["data"]?["redVipLevelIcon"]?.ToObject<string>()!;
        return user;
    }

    public async Task<PlaylistCollection> GetPlaylistCollection(string id)
    {
        var context = await GetFormString($"/user/playlist?uid={id}");
        var jsonPlaylists = context?["playlist"]!;
        var myLike = new PlaylistModel();
        var myList = new List<PlaylistModel>();
        var mySub = new List<PlaylistModel>();
        var i = 0;
        foreach (var jsonPlaylist in jsonPlaylists)
        {
            var playlist = new PlaylistModel
            {
                Name = jsonPlaylist["name"]!.ToObject<string>()!,
                Id = jsonPlaylist["id"]!.ToObject<string>()!,
                CoverImgUrl = jsonPlaylist["coverImgUrl"]!.ToObject<string>()!,
                Description = jsonPlaylist["description"]!.ToObject<string>()!
            };

            if (i == 0)
            {
                myLike = playlist;
                myLike.Name = "我喜欢的音乐";
                i = -1;
                continue;
            }

            if (jsonPlaylist["ordered"]!.ToObject<bool>())
                myList.Add(playlist);
            else
                mySub.Add(playlist);
        }

        return new PlaylistCollection { MyList = myList, MySub = mySub, MyLike = myLike };
    }

    public async Task<PlaylistModel[]> GetPlaylists(string id)
    {
        var context = await GetFormString($"/user/playlist?uid={id}");
        var jsonPlaylists = context?["playlist"]!;

        return jsonPlaylists.Select(x => new PlaylistModel
        {
            Name = x["name"]!.ToObject<string>()!,
            Id = x["id"]!.ToObject<string>()!,
            CoverImgUrl = x["coverImgUrl"]!.ToObject<string>()!,
            Description = x["description"]!.ToObject<string>()!
        }).ToArray();
    }

    public async Task<CloudModel> GetCloud()
    {
        var context = await GetFormString($"/user/cloud?cookie={Cookie}");
        if (context == null) return new CloudModel();
        var model = new CloudModel
        {
            Count = context["count"]!.ToObject<int>(),
            MaxSize = context["maxSize"]!.ToObject<long>().SizeToGB(),
            Size = context["size"]!.ToObject<long>().SizeToGB(),
            Songs = context["data"]!.Select(x => new SongModel
            {
                Name = x["simpleSong"]!["name"]!.ToObject<string>()!,
                Album = x["simpleSong"]!["al"]!["name"]!.ToObject<string>()!,
                AlbumId = x["simpleSong"]!["al"]!["id"]!.ToObject<string>()!,
                Artists = x["simpleSong"]!["ar"]!.Select(y => new ArtistModel(y)).ToArray(),
                Id = x["simpleSong"]!["id"]!.ToObject<string>()!,
                PicUrl = x["simpleSong"]!["al"]!["picUrl"]!.ToObject<string>()!,
                Time = x["simpleSong"]!["dt"]!.ToObject<string>()!
            }).ToArray()
        };
        return model;
    }

    public async Task<SongModel[]> RecordSong()
    {
        var context = await GetFormString($"/record/recent/song?limit=25&cookie={Cookie}");
        return context?["data"]?["list"]?.Select(x => new SongModel()
        {
            Id = x["data"]?["id"]?.ToObject<string>()!,
            Name = x["data"]?["name"]?.ToObject<string>()!,
            Artists = x["data"]?["ar"]?.ToObject<ArtistModel[]>() ?? [],
            Time = x["data"]?["dt"]?.ToObject<string>()!,
            AlbumId = x["data"]?["al"]?["id"]?.ToObject<string>()!,
            Album = x["data"]?["al"]?["name"]?.ToObject<string>()!,
            PicUrl = x["data"]?["al"]?["picUrl"]?.ToObject<string>()!,
        }).ToArray() ?? [];
    }

    public async Task<ReportModel> YearReport()
    {
        var context = await GetFormString($"/summary/annual?year=2023&cookie={Cookie}");
        var token = context?["data"];
        if (token == null) return new ReportModel();
        var a = token["annualSinger"]?["top5Songs"]!.Select(x => x["songId"]?.ToObject<string>()!).ToArray() ?? [];
        var hot = a.Aggregate("", (current, s) => current + s + ",");
        hot = hot[..^1];
        return new ReportModel()
        {
            RegTime = token["listenOverview"]?["regTime"]?.ToObject<string>()!,
            YearSong = token["yearOverview"]?["maxPlayedSong"]?["songName"]?.ToObject<string>()!,
            YearSongCount = token["yearOverview"]?["playCount"]?.ToObject<string>()!,
            YearSongId = token["yearOverview"]?["maxPlayedSong"]?["songId"]?.ToObject<string>()!,
            YearSongPicUrl = token["yearOverview"]?["maxPlayedSong"]?["songCoverUrl"]?.ToObject<string>()!,
            GenreRanks = token["genrePlayRank"]?["genreRank"]?.ToObject<GenreRank[]>() ?? [],
            Seasons = token["seasonsListen"]?.ToObject<Seasons>()!,
            KeyWord = token["keyWord"]?.ToObject<ReportKeyWord>()!,
            AnnualSong = token["annualSong"]?["songName"]?.ToObject<string>()!,
            AnnualSongId = token["annualSong"]?["songId"]?.ToObject<string>()!,
            AnnualSongArtist = token["annualSong"]?["artistNameList"]?.ToObject<string>()!,
            AnnualSongPicUrl = token["annualSong"]?["songPicUrl"]?.ToObject<string>()!,
            AnnualPlaylist = token["annualPlaylist"]?["items"]?.Select(x => new SongModel()
            {
                Id = x["songId"]?.ToObject<string>()!,
                Name = x["songName"]?.ToObject<string>()!,
                PicUrl = x["picUrl"]?.ToObject<string>()!,
                Artists =
                [
                    new ArtistModel()
                    {
                        Id = x["artistId"]?.ToObject<string>()!,
                        Name = x["artistName"]?.ToObject<string>()!
                    }
                ]
            }).ToArray() ?? [],
            AnnualAlbum = AlbumModel.ReportAlbum(token["annualPlaylistAlbum"]?["favoriteAlbum"]!),
            AnnualSinger = token["annualSinger"]?.ToObject<AnnualSinger>()!,
            AnnualSingerSongs = hot
        };
    }
}